package main.java.ERMDE.models;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import main.java.ERMDE.infrastructure.Func;
import main.java.ERMDE.infrastructure.IterableExtensions;


public class Relationship implements INameable {

	private List<Interface> relationshipEntites;
	private UUID id;
	private Boolean isComposition;
	private String name;
	private AttributeCollection attributes;

	public Relationship() {
		this(UUID.randomUUID(), "", false);
	}

	public Relationship(Interface entity1, Interface entity2) throws Exception {
		this(UUID.randomUUID(), "", false);
		if (!this.addRelationshipEntity(entity1)
				|| !this.addRelationshipEntity(entity2)) {
			throw new Exception();
		}
	}

	public Relationship(UUID id, String name, Boolean isComposition) {
		this.attributes = new AttributeCollection();
		this.relationshipEntites = new ArrayList<Interface>();
		this.id = id;
		this.isComposition = isComposition;
		this.name = name;
	}

	public Boolean addRelationshipEntity(Interface relationshipEntity) {
		for (Interface relEntity : this.relationshipEntites) {
			if (relEntity.getEntityId() == relationshipEntity.getEntityId()) {
				String role1 = relationshipEntity.getRole();
				String role2 = relEntity.getRole();

				if (role1 == null || role1 == "" || role2 == null
						|| role2 == "" || role1 == role2) {
					return false;
				}
			}
		}

		this.relationshipEntites.add(relationshipEntity);
		return true;
	}

	public Iterable<Interface> getRelationshipEntities() {
		return this.relationshipEntites;
	}

	public int count() {
		return relationshipEntites.size();
	}

	public void setRelationshipEntities(List<Interface> relationshipEntites) {
		this.relationshipEntites = relationshipEntites;
	}

	public UUID getId() {
		return this.id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void isComposition(Boolean isComposition) {
		this.isComposition = isComposition;
	}

	public Boolean isComposition() {
		return isComposition;
	}

	public AttributeCollection getAttributes() {
		return this.attributes;
	}

	public void setAttributes(AttributeCollection attributes) {
		this.attributes = attributes;
	}

	public boolean hasWeakEntity() {
		if (this.relationshipEntites.size() != 2) {
			return false;
		}

		Func<Interface, Boolean, Boolean> cmp = new Func<Interface, Boolean, Boolean>() {

			@Override
			public Boolean execute(Interface relationshipEntity,
					Boolean isStrong) {
				return relationshipEntity.isStrongEntity() == isStrong;
			}

		};

		return IterableExtensions.firstOrDefault(this.relationshipEntites, cmp,
				true) != null;
	}

	public Interface getWeakEntity() {
		Func<Interface, Boolean, Boolean> cmp = new Func<Interface, Boolean, Boolean>() {

			@Override
			public Boolean execute(Interface relationshipEntity,
					Boolean isStrong) {
				return relationshipEntity.isStrongEntity() == isStrong;
			}

		};

		return IterableExtensions.firstOrDefault(this.relationshipEntites, cmp,
				false);
	}

	public Interface getStrongEntity() {
		Func<Interface, Boolean, Boolean> cmp = new Func<Interface, Boolean, Boolean>() {

			@Override
			public Boolean execute(Interface relationshipEntity,
					Boolean isStrong) {
				return relationshipEntity.isStrongEntity() == isStrong;
			}

		};

		return IterableExtensions.firstOrDefault(this.relationshipEntites, cmp,
				true);
	}

	@Override
	public String toString() {
		return this.name != null ? this.name : this.id.toString();
	}
}
